﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Drawing.Imaging;
using System.Threading;
using MovieDbLib.Data.Banner;
using System.ComponentModel;

namespace MovieDbBrowser
{
  /// <summary>
  /// Interaction logic for MovieDbBannerControl.xaml
  /// </summary>
  public partial class MovieDbBannerControl : UserControl
  {
    #region private properties
    private delegate void ImageChangerDelegate(System.Drawing.Image _image);
    private delegate void BoolDelegate(bool _value);
    private List<MovieDbBanner> m_imageList;
    private int m_index = 0;
    private Image m_defaultImage;
    private Size m_buttonSize;
    private Thread m_latestLoadingThread; //thread that loads the LATEST image (which should be shown after loading)
    private Image m_unavailableImage;
    private bool m_useThumbIfPossible = true;
    #endregion


    public MovieDbBannerControl()
    {
      InitializeComponent();
    }

    #region public properties for the banner control
    /// <summary>
    /// List of images for this control
    /// </summary>
    [Description("List of banner images")]
    public List<MovieDbBanner> BannerImages
    {
      set
      {
        m_imageList = value;
        if (m_imageList != null)
        {
          if (m_imageList.Count > 0)
          {
            m_index = 0;
            SetBannerImage(value[0]);
          }
          if (m_imageList.Count <= 1)
          {
            cmdNext.Visibility = Visibility.Hidden;
            cmdPrev.Visibility = Visibility.Hidden;
          }
          else
          {
            cmdPrev.Visibility = Visibility.Hidden;
            cmdNext.Visibility = Visibility.Visible;
          }
        }
        else
        {
          imgBannerImage.Source = null;
          cmdPrev.Visibility = Visibility.Hidden;
          cmdNext.Visibility = Visibility.Hidden;
        }
      }
      get { return m_imageList; }
    }

    /// <summary>
    /// Will use the thumbnail of the image
    /// </summary>
    [Description("Will use the thumbnail of the image if a thumbnail is available")]
    public bool UseThumb
    {
      get { return m_useThumbIfPossible; }
      set { m_useThumbIfPossible = value; }
    }

    /// <summary>
    /// Set the new banner image
    /// </summary>
    /// <param name="_value"></param>
    private void SetBannerImage(MovieDbBanner _value)
    {
      Thread imageLoader = new Thread(new ParameterizedThreadStart(DoBannerLoad));
      m_latestLoadingThread = imageLoader;
      imageLoader.Priority = ThreadPriority.Lowest;
      imageLoader.Name = "Imageloader_" + _value.Id;
      imageLoader.Start(_value);

    }

    


    #endregion


    public void SetBannerImage(System.Drawing.Image _image)
    {
      if (_image != null)
      {
        BitmapImage bi = new BitmapImage();
        bi.BeginInit();
        MemoryStream ms = new MemoryStream();

        // Save to a memory stream...
        _image.Save(ms, ImageFormat.Jpeg);

        // Rewind the stream...
        ms.Seek(0, SeekOrigin.Begin);

        // Tell the WPF image to use this stream...
        bi.StreamSource = ms;

        bi.EndInit();
        imgBannerImage.Source = bi;
      }
    }

    public void SetBannerImageThreadSafe(System.Drawing.Image _image)
    {
      if (imgBannerImage.Dispatcher.CheckAccess())
      {
        SetBannerImage(_image);
      }
      else
      {
        ImageChangerDelegate changer = new ImageChangerDelegate(SetBannerImageThreadSafe);

        imgBannerImage.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Send,
                                              changer, _image);
;
      }
    }

    private void SetLoadingVisibleThreadSafe(bool _visible)
    {
      if (busyAnimation.Dispatcher.CheckAccess())
      {
        busyAnimation.Visibility = _visible ? Visibility.Visible : Visibility.Hidden;
      }
      else
      {
        busyAnimation.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Send,
                                              new BoolDelegate(SetLoadingVisibleThreadSafe), _visible);
        ;
      } 

      //throw new NotImplementedException();
    }


    private void cmdNext_MouseUp(object sender, MouseButtonEventArgs e)
    {
      cmdNext.Width = 25;
      cmdNext.Height = 25;

      if (m_imageList != null && m_imageList.Count != 0)
      {
        cmdPrev.Visibility = Visibility.Visible;
        m_index++;
        //if (IndexChanged != null) IndexChanged(new EventArgs());
        SetBannerImage(m_imageList[m_index]);
        if (m_index >= m_imageList.Count - 1)
        {
          cmdNext.Visibility = Visibility.Hidden;
        }
      }
    }

    private void cmdPrev_MouseUp(object sender, MouseButtonEventArgs e)
    {
      cmdPrev.Width = 25;
      cmdPrev.Height = 25;

      if (m_imageList != null && m_imageList.Count != 0)
      {
        cmdNext.Visibility = Visibility.Visible;
        m_index--;
        //if (IndexChanged != null) IndexChanged(new EventArgs());
        SetBannerImage(m_imageList[m_index]);
        if (m_index <= 0)
        {
          cmdPrev.Visibility = Visibility.Hidden;
        }
      }

    }

    private void cmdNext_MouseDown(object sender, MouseButtonEventArgs e)
    {
      cmdNext.Width = 24;
      cmdNext.Height = 24;
    }

    private void cmdPrev_MouseDown(object sender, MouseButtonEventArgs e)
    {
      cmdPrev.Width = 24;
      cmdPrev.Height = 24;
    }

    #region banner loading logic
    /// <summary>
    /// Do a banner load within it's own thread
    /// </summary>
    /// <param name="_param"></param>
    private void DoBannerLoad(object _param)
    {
      MovieDbBanner banner = (MovieDbBanner)_param;
      try
      {
        if (banner != null)
        {
          int index = m_index;
          bool hasThumb = banner.Thumbnail != null;
          if (m_useThumbIfPossible && hasThumb)
          {//load the thumbnail
            if (!banner.Thumbnail.IsLoaded)
            {
              SetBannerImageThreadSafe(null);
              SetLoadingVisibleThreadSafe(true);
              banner.Thumbnail.LoadBanner();
            }
          }
          else
          {
            if (!banner.Original.IsLoaded)
            {
              SetBannerImageThreadSafe(null);
              SetLoadingVisibleThreadSafe(true);
              banner.Original.LoadBanner();
            }
          }

          lock (m_latestLoadingThread)
          {
            if (Thread.CurrentThread == m_latestLoadingThread)
            {
              //Console.WriteLine("Loading finished of " + banner.Id);
              if (m_useThumbIfPossible && hasThumb && banner.Thumbnail.IsLoaded)
              {
                SetLoadingVisibleThreadSafe(false);
                SetBannerImageThreadSafe(banner.Thumbnail.BannerImage);
              }
              else if (banner.Original.IsLoaded)
              {//banner was successfully loaded
                SetLoadingVisibleThreadSafe(false);
                SetBannerImageThreadSafe(banner.Original.BannerImage);
              }
              else
              {//couldn't load the banner
                SetLoadingVisibleThreadSafe(false);
              }
            }
            else
            {
              //Console.WriteLine("Didn't load " + banner.Id + " because it's not the latest image");
            }
          }
        }
        else
        {//no banner information available -> use default image if there is one
          SetLoadingVisibleThreadSafe(false);
          SetBannerImageThreadSafe(null);
        }
      }
      catch (ThreadAbortException)
      {
        //Console.WriteLine("Bannercontrol aborted loading");
      }
    }




    #endregion
  }
}
